gitgit.videolan.org / vlc.git / blob

commit
 ? search: 
 re
summary | shortlog | log | commit | commitdiff | tree
history | raw | HEAD
ci_filters: fix pointer used for src converter
[vlc.git] / modules / mux / mp4.c
   1 /*****************************************************************************
   2  * mp4.c: mp4/mov muxer
   3  *****************************************************************************
   4  * Copyright (C) 2001, 2002, 2003, 2006 VLC authors and VideoLAN
   5  * $Id$
   6  *
   7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
   8  *          Gildas Bazin <gbazin at videolan dot org>
   9  *
  10  * This program is free software; you can redistribute it and/or modify it
  11  * under the terms of the GNU Lesser General Public License as published by
  12  * the Free Software Foundation; either version 2.1 of the License, or
  13  * (at your option) any later version.
  14  *
  15  * This program is distributed in the hope that it will be useful,
  16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18  * GNU Lesser General Public License for more details.
  19  *
  20  * You should have received a copy of the GNU Lesser General Public License
  21  * along with this program; if not, write to the Free Software Foundation,
  22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23  *****************************************************************************/
  24 
  25 /*****************************************************************************
  26  * Preamble
  27  *****************************************************************************/
  28 
  29 #ifdef HAVE_CONFIG_H
  30 # include "config.h"
  31 #endif
  32 
  33 #include <vlc_common.h>
  34 #include <vlc_plugin.h>
  35 #include <vlc_sout.h>
  36 #include <vlc_block.h>
  37 
  38 #include <time.h>
  39 
  40 #include <vlc_iso_lang.h>
  41 #include <vlc_meta.h>
  42 
  43 #include "../demux/mpeg/mpeg_parser_helpers.h"
  44 
  45 /*****************************************************************************
  46  * Module descriptor
  47  *****************************************************************************/
  48 #define FASTSTART_TEXT N_("Create \"Fast Start\" files")
  49 #define FASTSTART_LONGTEXT N_(\
  50     "Create \"Fast Start\" files. " \
  51     "\"Fast Start\" files are optimized for downloads and allow the user " \
  52     "to start previewing the file while it is downloading.")
  53 
  54 static int  Open   (vlc_object_t *);
  55 static void Close  (vlc_object_t *);
  56 
  57 #define SOUT_CFG_PREFIX "sout-mp4-"
  58 
  59 vlc_module_begin ()
  60     set_description(N_("MP4/MOV muxer"))
  61     set_category(CAT_SOUT)
  62     set_subcategory(SUBCAT_SOUT_MUX)
  63     set_shortname("MP4")
  64 
  65     add_bool(SOUT_CFG_PREFIX "faststart", true,
  66               FASTSTART_TEXT, FASTSTART_LONGTEXT,
  67               true)
  68     set_capability("sout mux", 5)
  69     add_shortcut("mp4", "mov", "3gp")
  70     set_callbacks(Open, Close)
  71 vlc_module_end ()
  72 
  73 /*****************************************************************************
  74  * Exported prototypes
  75  *****************************************************************************/
  76 static const char *const ppsz_sout_options[] = {
  77     "faststart", NULL
  78 };
  79 
  80 static int Control(sout_mux_t *, int, va_list);
  81 static int AddStream(sout_mux_t *, sout_input_t *);
  82 static int DelStream(sout_mux_t *, sout_input_t *);
  83 static int Mux      (sout_mux_t *);
  84 
  85 /*****************************************************************************
  86  * Local prototypes
  87  *****************************************************************************/
  88 typedef struct
  89 {
  90     uint64_t i_pos;
  91     int      i_size;
  92 
  93     mtime_t  i_pts_dts;
  94     mtime_t  i_length;
  95     unsigned int i_flags;
  96 
  97 } mp4_entry_t;
  98 
  99 typedef struct
 100 {
 101     es_format_t   fmt;
 102     unsigned int  i_track_id;
 103 
 104     /* index */
 105     unsigned int i_entry_count;
 106     unsigned int i_entry_max;
 107     mp4_entry_t  *entry;
 108     int64_t      i_length_neg;
 109 
 110     /* stats */
 111     int64_t      i_dts_start; /* applies to current segment only */
 112     int64_t      i_duration;
 113     uint32_t     i_timescale;
 114     mtime_t      i_starttime; /* the really first packet */
 115     bool         b_hasbframes;
 116 
 117     /* for later stco fix-up (fast start files) */
 118     uint64_t i_stco_pos;
 119     bool b_stco64;
 120 
 121     /* for spu */
 122     int64_t i_last_dts; /* applies to current segment only */
 123 
 124 } mp4_stream_t;
 125 
 126 struct sout_mux_sys_t
 127 {
 128     bool b_mov;
 129     bool b_3gp;
 130     bool b_64_ext;
 131     bool b_fast_start;
 132 
 133     uint64_t i_mdat_pos;
 134     uint64_t i_pos;
 135     mtime_t  i_duration;
 136 
 137     unsigned int   i_nb_streams;
 138     mp4_stream_t **pp_streams;
 139 };
 140 
 141 typedef struct bo_t
 142 {
 143     block_t    *b;
 144     size_t     len;
 145 } bo_t;
 146 
 147 static void bo_init     (bo_t *);
 148 static void bo_add_8    (bo_t *, uint8_t);
 149 static void bo_add_16be (bo_t *, uint16_t);
 150 static void bo_add_24be (bo_t *, uint32_t);
 151 static void bo_add_32be (bo_t *, uint32_t);
 152 static void bo_add_64be (bo_t *, uint64_t);
 153 static void bo_add_fourcc(bo_t *, const char *);
 154 static void bo_add_mem  (bo_t *, int , uint8_t *);
 155 static void bo_add_descr(bo_t *, uint8_t , uint32_t);
 156 
 157 static void bo_fix_32be (bo_t *, int , uint32_t);
 158 
 159 static bo_t *box_new     (const char *fcc);
 160 static bo_t *box_full_new(const char *fcc, uint8_t v, uint32_t f);
 161 static void  box_fix     (bo_t *box);
 162 static void  box_gather  (bo_t *box, bo_t *box2);
 163 
 164 static void box_send(sout_mux_t *p_mux,  bo_t *box);
 165 
 166 static bo_t *GetMoovBox(sout_mux_t *p_mux);
 167 
 168 static block_t *ConvertSUBT(block_t *);
 169 static block_t *ConvertFromAnnexB(block_t *);
 170 
 171 static const char avc1_start_code[4] = { 0, 0, 0, 1 };
 172 
 173 /*****************************************************************************
 174  * Open:
 175  *****************************************************************************/
 176 static int Open(vlc_object_t *p_this)
 177 {
 178     sout_mux_t      *p_mux = (sout_mux_t*)p_this;
 179     sout_mux_sys_t  *p_sys;
 180     bo_t            *box;
 181 
 182     msg_Dbg(p_mux, "Mp4 muxer opened");
 183     config_ChainParse(p_mux, SOUT_CFG_PREFIX, ppsz_sout_options, p_mux->p_cfg);
 184 
 185     p_mux->pf_control   = Control;
 186     p_mux->pf_addstream = AddStream;
 187     p_mux->pf_delstream = DelStream;
 188     p_mux->pf_mux       = Mux;
 189     p_mux->p_sys        = p_sys = malloc(sizeof(sout_mux_sys_t));
 190     if (!p_sys)
 191         return VLC_ENOMEM;
 192     p_sys->i_pos        = 0;
 193     p_sys->i_nb_streams = 0;
 194     p_sys->pp_streams   = NULL;
 195     p_sys->i_mdat_pos   = 0;
 196     p_sys->b_mov        = p_mux->psz_mux && !strcmp(p_mux->psz_mux, "mov");
 197     p_sys->b_3gp        = p_mux->psz_mux && !strcmp(p_mux->psz_mux, "3gp");
 198     p_sys->i_duration   = 0;
 199 
 200     if (!p_sys->b_mov) {
 201         /* Now add ftyp header */
 202         box = box_new("ftyp");
 203         if (p_sys->b_3gp)
 204             bo_add_fourcc(box, "3gp6");
 205         else
 206             bo_add_fourcc(box, "isom");
 207         bo_add_32be  (box, 0);
 208         if (p_sys->b_3gp)
 209             bo_add_fourcc(box, "3gp4");
 210         else
 211             bo_add_fourcc(box, "mp41");
 212         bo_add_fourcc(box, "avc1");
 213         bo_add_fourcc(box, "qt  ");
 214         box_fix(box);
 215 
 216         p_sys->i_pos += box->len;
 217         p_sys->i_mdat_pos = p_sys->i_pos;
 218 
 219         box_send(p_mux, box);
 220     }
 221 
 222     /* FIXME FIXME
 223      * Quicktime actually doesn't like the 64 bits extensions !!! */
 224     p_sys->b_64_ext = false;
 225 
 226     /* Now add mdat header */
 227     box = box_new("mdat");
 228     bo_add_64be  (box, 0); // enough to store an extended size
 229 
 230     p_sys->i_pos += box->len;
 231 
 232     box_send(p_mux, box);
 233 
 234     return VLC_SUCCESS;
 235 }
 236 
 237 /*****************************************************************************
 238  * Close:
 239  *****************************************************************************/
 240 static void Close(vlc_object_t *p_this)
 241 {
 242     sout_mux_t      *p_mux = (sout_mux_t*)p_this;
 243     sout_mux_sys_t  *p_sys = p_mux->p_sys;
 244 
 245     msg_Dbg(p_mux, "Close");
 246 
 247     /* Update mdat size */
 248     bo_t bo;
 249     bo_init(&bo);
 250     if (p_sys->i_pos - p_sys->i_mdat_pos >= (((uint64_t)1)<<32)) {
 251         /* Extended size */
 252         bo_add_32be  (&bo, 1);
 253         bo_add_fourcc(&bo, "mdat");
 254         bo_add_64be  (&bo, p_sys->i_pos - p_sys->i_mdat_pos);
 255     } else {
 256         bo_add_32be  (&bo, 8);
 257         bo_add_fourcc(&bo, "wide");
 258         bo_add_32be  (&bo, p_sys->i_pos - p_sys->i_mdat_pos - 8);
 259         bo_add_fourcc(&bo, "mdat");
 260     }
 261 
 262     bo.b->i_buffer = bo.len;
 263     sout_AccessOutSeek(p_mux->p_access, p_sys->i_mdat_pos);
 264     sout_AccessOutWrite(p_mux->p_access, bo.b);
 265 
 266     /* Create MOOV header */
 267     uint64_t i_moov_pos = p_sys->i_pos;
 268     bo_t *moov = GetMoovBox(p_mux);
 269 
 270     /* Check we need to create "fast start" files */
 271     p_sys->b_fast_start = var_GetBool(p_this, SOUT_CFG_PREFIX "faststart");
 272     while (p_sys->b_fast_start) {
 273         /* Move data to the end of the file so we can fit the moov header
 274          * at the start */
 275         int64_t i_size = p_sys->i_pos - p_sys->i_mdat_pos;
 276         int i_moov_size = moov->len;
 277 
 278         while (i_size > 0) {
 279             int64_t i_chunk = __MIN(32768, i_size);
 280             block_t *p_buf = block_Alloc(i_chunk);
 281             sout_AccessOutSeek(p_mux->p_access,
 282                                 p_sys->i_mdat_pos + i_size - i_chunk);
 283             if (sout_AccessOutRead(p_mux->p_access, p_buf) < i_chunk) {
 284                 msg_Warn(p_this, "read() not supported by access output, "
 285                           "won't create a fast start file");
 286                 p_sys->b_fast_start = false;
 287                 block_Release(p_buf);
 288                 break;
 289             }
 290             sout_AccessOutSeek(p_mux->p_access, p_sys->i_mdat_pos + i_size +
 291                                 i_moov_size - i_chunk);
 292             sout_AccessOutWrite(p_mux->p_access, p_buf);
 293             i_size -= i_chunk;
 294         }
 295 
 296         if (!p_sys->b_fast_start)
 297             break;
 298 
 299         /* Fix-up samples to chunks table in MOOV header */
 300         for (unsigned int i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++) {
 301             mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
 302 
 303             moov->len = p_stream->i_stco_pos;
 304             for (unsigned i = 0; i < p_stream->i_entry_count; ) {
 305                 mp4_entry_t *entry = p_stream->entry;
 306                 if (p_stream->b_stco64)
 307                     bo_add_64be(moov, entry[i].i_pos + i_moov_size);
 308                 else
 309                     bo_add_32be(moov, entry[i].i_pos + i_moov_size);
 310 
 311                 for (; i < p_stream->i_entry_count; i++)
 312                     if (i >= p_stream->i_entry_count - 1 ||
 313                         entry[i].i_pos + entry[i].i_size != entry[i+1].i_pos) {
 314                         i++;
 315                         break;
 316                     }
 317             }
 318         }
 319 
 320         moov->len = i_moov_size;
 321         i_moov_pos = p_sys->i_mdat_pos;
 322         p_sys->b_fast_start = false;
 323     }
 324 
 325     /* Write MOOV header */
 326     sout_AccessOutSeek(p_mux->p_access, i_moov_pos);
 327     box_send(p_mux, moov);
 328 
 329     /* Clean-up */
 330     for (unsigned int i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++) {
 331         mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
 332 
 333         es_format_Clean(&p_stream->fmt);
 334         free(p_stream->entry);
 335         free(p_stream);
 336     }
 337     if (p_sys->i_nb_streams)
 338         free(p_sys->pp_streams);
 339     free(p_sys);
 340 }
 341 
 342 /*****************************************************************************
 343  * Control:
 344  *****************************************************************************/
 345 static int Control(sout_mux_t *p_mux, int i_query, va_list args)
 346 {
 347     VLC_UNUSED(p_mux);
 348     bool *pb_bool;
 349 
 350     switch(i_query)
 351     {
 352     case MUX_CAN_ADD_STREAM_WHILE_MUXING:
 353         pb_bool = (bool*)va_arg(args, bool *);
 354         *pb_bool = false;
 355         return VLC_SUCCESS;
 356 
 357     case MUX_GET_ADD_STREAM_WAIT:
 358         pb_bool = (bool*)va_arg(args, bool *);
 359         *pb_bool = true;
 360         return VLC_SUCCESS;
 361 
 362     case MUX_GET_MIME:   /* Not needed, as not streamable */
 363     default:
 364         return VLC_EGENERIC;
 365     }
 366 }
 367 
 368 /*****************************************************************************
 369  * AddStream:
 370  *****************************************************************************/
 371 static int AddStream(sout_mux_t *p_mux, sout_input_t *p_input)
 372 {
 373     sout_mux_sys_t  *p_sys = p_mux->p_sys;
 374     mp4_stream_t    *p_stream;
 375 
 376     switch(p_input->p_fmt->i_codec)
 377     {
 378     case VLC_CODEC_MP4A:
 379     case VLC_CODEC_MP4V:
 380     case VLC_CODEC_MPGA:
 381     case VLC_CODEC_MPGV:
 382     case VLC_CODEC_MP2V:
 383     case VLC_CODEC_MP1V:
 384     case VLC_CODEC_MJPG:
 385     case VLC_CODEC_MJPGB:
 386     case VLC_CODEC_SVQ1:
 387     case VLC_CODEC_SVQ3:
 388     case VLC_CODEC_H263:
 389     case VLC_CODEC_H264:
 390     case VLC_CODEC_HEVC:
 391     case VLC_CODEC_AMR_NB:
 392     case VLC_CODEC_AMR_WB:
 393     case VLC_CODEC_YV12:
 394     case VLC_CODEC_YUYV:
 395         break;
 396     case VLC_CODEC_SUBT:
 397         msg_Warn(p_mux, "subtitle track added like in .mov (even when creating .mp4)");
 398         break;
 399     default:
 400         msg_Err(p_mux, "unsupported codec %4.4s in mp4",
 401                  (char*)&p_input->p_fmt->i_codec);
 402         return VLC_EGENERIC;
 403     }
 404 
 405     p_stream = malloc(sizeof(mp4_stream_t));
 406     if (!p_stream)
 407         return VLC_ENOMEM;
 408     es_format_Copy(&p_stream->fmt, p_input->p_fmt);
 409     p_stream->i_track_id    = p_sys->i_nb_streams + 1;
 410     p_stream->i_length_neg  = 0;
 411     p_stream->i_entry_count = 0;
 412     p_stream->i_entry_max   = 1000;
 413     p_stream->entry         =
 414         calloc(p_stream->i_entry_max, sizeof(mp4_entry_t));
 415     p_stream->i_dts_start   = 0;
 416     p_stream->i_duration    = 0;
 417     if (p_stream->fmt.i_cat == AUDIO_ES)
 418         p_stream->i_timescale = p_stream->fmt.audio.i_rate;
 419     else
 420         p_stream->i_timescale = CLOCK_FREQ;
 421     p_stream->i_starttime   = p_sys->i_duration;
 422     p_stream->b_hasbframes  = false;
 423 
 424     p_stream->i_last_dts    = 0;
 425 
 426     p_input->p_sys          = p_stream;
 427 
 428     msg_Dbg(p_mux, "adding input");
 429 
 430     TAB_APPEND(p_sys->i_nb_streams, p_sys->pp_streams, p_stream);
 431     return VLC_SUCCESS;
 432 }
 433 
 434 /*****************************************************************************
 435  * DelStream:
 436  *****************************************************************************/
 437 static int DelStream(sout_mux_t *p_mux, sout_input_t *p_input)
 438 {
 439     VLC_UNUSED(p_input);
 440     msg_Dbg(p_mux, "removing input");
 441     return VLC_SUCCESS;
 442 }
 443 
 444 /*****************************************************************************
 445  * Mux:
 446  *****************************************************************************/
 447 static int Mux(sout_mux_t *p_mux)
 448 {
 449     sout_mux_sys_t *p_sys = p_mux->p_sys;
 450 
 451     for (;;) {
 452         int i_stream = sout_MuxGetStream(p_mux, 2, NULL);
 453         if (i_stream < 0)
 454             return(VLC_SUCCESS);
 455 
 456         sout_input_t *p_input  = p_mux->pp_inputs[i_stream];
 457         mp4_stream_t *p_stream = (mp4_stream_t*)p_input->p_sys;
 458 
 459         block_t *p_data;
 460         do {
 461             p_data = block_FifoGet(p_input->p_fifo);
 462             if (p_stream->fmt.i_codec == VLC_CODEC_H264 ||
 463                 p_stream->fmt.i_codec == VLC_CODEC_HEVC)
 464                 p_data = ConvertFromAnnexB(p_data);
 465             else if (p_stream->fmt.i_codec == VLC_CODEC_SUBT)
 466                 p_data = ConvertSUBT(p_data);
 467         } while (!p_data);
 468 
 469         /* Reset reference dts in case of discontinuity (ex: gather sout) */
 470         if ( p_stream->i_entry_count == 0 || p_data->i_flags & BLOCK_FLAG_DISCONTINUITY )
 471         {
 472             p_stream->i_dts_start = p_data->i_dts;
 473             p_stream->i_last_dts = p_data->i_dts;
 474             p_stream->i_length_neg = 0;
 475         }
 476 
 477         if (p_stream->fmt.i_cat != SPU_ES) {
 478             /* Fix length of the sample */
 479             if (block_FifoCount(p_input->p_fifo) > 0) {
 480                 block_t *p_next = block_FifoShow(p_input->p_fifo);
 481                 if ( p_next->i_flags & BLOCK_FLAG_DISCONTINUITY )
 482                 { /* we have no way to know real length except by decoding */
 483                     if ( p_stream->fmt.i_cat == VIDEO_ES )
 484                     {
 485                         p_data->i_length = CLOCK_FREQ *
 486                                            p_stream->fmt.video.i_frame_rate_base /
 487                                            p_stream->fmt.video.i_frame_rate;
 488                         msg_Dbg( p_mux, "video track %u fixup to %"PRId64" for sample %u",
 489                                  p_stream->i_track_id, p_data->i_length, p_stream->i_entry_count );
 490                     }
 491                     else if ( p_stream->fmt.i_cat == AUDIO_ES &&
 492                               p_stream->fmt.audio.i_rate &&
 493                               p_data->i_nb_samples )
 494                     {
 495                         p_data->i_length = CLOCK_FREQ * p_data->i_nb_samples /
 496                                            p_stream->fmt.audio.i_rate;
 497                         msg_Dbg( p_mux, "audio track %u fixup to %"PRId64" for sample %u",
 498                                  p_stream->i_track_id, p_data->i_length, p_stream->i_entry_count );
 499                     }
 500                     else if ( p_data->i_length <= 0 )
 501                     {
 502                         msg_Warn( p_mux, "unknown length for track %u sample %u",
 503                                   p_stream->i_track_id, p_stream->i_entry_count );
 504                         p_data->i_length = 1;
 505                     }
 506                 }
 507                 else
 508                 {
 509                     int64_t i_diff  = p_next->i_dts - p_data->i_dts;
 510                     if (i_diff < CLOCK_FREQ) /* protection */
 511                         p_data->i_length = i_diff;
 512                 }
 513             }
 514             if (p_data->i_length <= 0) {
 515                 msg_Warn(p_mux, "i_length <= 0");
 516                 p_stream->i_length_neg += p_data->i_length - 1;
 517                 p_data->i_length = 1;
 518             } else if (p_stream->i_length_neg < 0) {
 519                 int64_t i_recover = __MIN(p_data->i_length / 4, - p_stream->i_length_neg);
 520 
 521                 p_data->i_length -= i_recover;
 522                 p_stream->i_length_neg += i_recover;
 523             }
 524         }
 525 
 526         if (p_stream->fmt.i_cat == SPU_ES && p_stream->i_entry_count > 0) {
 527             int64_t i_length = p_data->i_dts - p_stream->i_last_dts;
 528 
 529             if (i_length <= 0) /* FIXME handle this broken case */
 530                 i_length = 1;
 531 
 532             /* Fix last entry */
 533             if (p_stream->entry[p_stream->i_entry_count-1].i_length <= 0)
 534                 p_stream->entry[p_stream->i_entry_count-1].i_length = i_length;
 535         }
 536 
 537         /* add index entry */
 538         mp4_entry_t *e = &p_stream->entry[p_stream->i_entry_count];
 539         e->i_pos    = p_sys->i_pos;
 540         e->i_size   = p_data->i_buffer;
 541 
 542         if ( p_data->i_dts > VLC_TS_INVALID && p_data->i_pts > p_data->i_dts )
 543         {
 544             e->i_pts_dts = p_data->i_pts - p_data->i_dts;
 545             if ( !p_stream->b_hasbframes )
 546                 p_stream->b_hasbframes = true;
 547         }
 548         else e->i_pts_dts = 0;
 549 
 550         e->i_length = p_data->i_length;
 551         e->i_flags  = p_data->i_flags;
 552 
 553         p_stream->i_entry_count++;
 554         /* XXX: -1 to always have 2 entry for easy adding of empty SPU */
 555         if (p_stream->i_entry_count >= p_stream->i_entry_max - 1) {
 556             p_stream->i_entry_max += 1000;
 557             p_stream->entry = xrealloc(p_stream->entry,
 558                          p_stream->i_entry_max * sizeof(mp4_entry_t));
 559         }
 560 
 561         /* update */
 562         p_stream->i_duration += __MAX( 0, p_data->i_length );
 563         p_sys->i_pos += p_data->i_buffer;
 564 
 565         /* Save the DTS for SPU */
 566         p_stream->i_last_dts = p_data->i_dts;
 567 
 568         /* write data */
 569         sout_AccessOutWrite(p_mux->p_access, p_data);
 570 
 571         /* close subtitle with empty frame */
 572         if (p_stream->fmt.i_cat == SPU_ES) {
 573             int64_t i_length = p_stream->entry[p_stream->i_entry_count-1].i_length;
 574 
 575             if ( i_length != 0 && (p_data = block_Alloc(3)) ) {
 576                 /* TODO */
 577                 msg_Dbg(p_mux, "writing an empty sub") ;
 578 
 579                 /* Append a idx entry */
 580                 mp4_entry_t *e = &p_stream->entry[p_stream->i_entry_count];
 581                 e->i_pos    = p_sys->i_pos;
 582                 e->i_size   = 3;
 583                 e->i_pts_dts= 0;
 584                 e->i_length = 0;
 585                 e->i_flags  = 0;
 586 
 587                 /* XXX: No need to grow the entry here */
 588                 p_stream->i_entry_count++;
 589 
 590                 /* Fix last dts */
 591                 p_stream->i_last_dts += i_length;
 592 
 593                 /* Write a " " */
 594                 p_data->i_dts = p_stream->i_last_dts;
 595                 p_data->i_dts = p_data->i_pts;
 596                 p_data->p_buffer[0] = 0;
 597                 p_data->p_buffer[1] = 1;
 598                 p_data->p_buffer[2] = ' ';
 599 
 600                 p_sys->i_pos += p_data->i_buffer;
 601 
 602                 sout_AccessOutWrite(p_mux->p_access, p_data);
 603             }
 604 
 605             /* Fix duration = current segment starttime + duration within */
 606             p_stream->i_duration = p_stream->i_starttime + ( p_stream->i_last_dts - p_stream->i_dts_start );
 607         }
 608     }
 609 
 610     /* Update the global segment/media duration */
 611     for ( unsigned int i=0; i<p_sys->i_nb_streams; i++ )
 612     {
 613         if ( p_sys->pp_streams[i]->i_duration > p_sys->i_duration )
 614             p_sys->i_duration = p_sys->pp_streams[i]->i_duration;
 615     }
 616 
 617     return(VLC_SUCCESS);
 618 }
 619 
 620 /*****************************************************************************
 621  *
 622  *****************************************************************************/
 623 static block_t *ConvertSUBT(block_t *p_block)
 624 {
 625     p_block = block_Realloc(p_block, 2, p_block->i_buffer);
 626 
 627     /* No trailling '\0' */
 628     if (p_block->i_buffer > 2 && p_block->p_buffer[p_block->i_buffer-1] == '\0')
 629         p_block->i_buffer--;
 630 
 631     p_block->p_buffer[0] = ((p_block->i_buffer - 2) >> 8)&0xff;
 632     p_block->p_buffer[1] = ((p_block->i_buffer - 2)     )&0xff;
 633 
 634     return p_block;
 635 }
 636 
 637 static block_t *ConvertFromAnnexB(block_t *p_block)
 638 {
 639     uint8_t *last = p_block->p_buffer;  /* Assume it starts with 0x00000001 */
 640     uint8_t *dat  = &p_block->p_buffer[4];
 641     uint8_t *end = &p_block->p_buffer[p_block->i_buffer];
 642 
 643 
 644     /* Replace the 4 bytes start code with 4 bytes size,
 645      * FIXME are all startcodes 4 bytes ? (I don't think :(*/
 646     while (dat < end) {
 647         while (dat < end - 4) {
 648             if (!memcmp(dat, avc1_start_code, 4))
 649                 break;
 650             dat++;
 651         }
 652         if (dat >= end - 4)
 653             dat = end;
 654 
 655         /* Fix size */
 656         int i_size = dat - &last[4];
 657         last[0] = (i_size >> 24)&0xff;
 658         last[1] = (i_size >> 16)&0xff;
 659         last[2] = (i_size >>  8)&0xff;
 660         last[3] = (i_size      )&0xff;
 661 
 662         /* Skip blocks with SPS/PPS */
 663         //if ((last[4]&0x1f) == 7 || (last[4]&0x1f) == 8)
 664         //    ; // FIXME Find a way to skip dat without frelling everything
 665         last = dat;
 666         dat += 4;
 667     }
 668     return p_block;
 669 }
 670 
 671 static bo_t *GetESDS(mp4_stream_t *p_stream)
 672 {
 673     bo_t *esds;
 674     int64_t i_bitrate_avg = 0;
 675     int64_t i_bitrate_max = 0;
 676 
 677     /* Compute avg/max bitrate */
 678     for (unsigned i = 0; i < p_stream->i_entry_count; i++) {
 679         i_bitrate_avg += p_stream->entry[i].i_size;
 680         if (p_stream->entry[i].i_length > 0) {
 681             int64_t i_bitrate = INT64_C(8000000) * p_stream->entry[i].i_size / p_stream->entry[i].i_length;
 682             if (i_bitrate > i_bitrate_max)
 683                 i_bitrate_max = i_bitrate;
 684         }
 685     }
 686 
 687     if (p_stream->i_duration > 0)
 688         i_bitrate_avg = INT64_C(8000000) * i_bitrate_avg / p_stream->i_duration;
 689     else
 690         i_bitrate_avg = 0;
 691     if (i_bitrate_max <= 1)
 692         i_bitrate_max = 0x7fffffff;
 693 
 694     /* */
 695     int i_decoder_specific_info_size = (p_stream->fmt.i_extra > 0) ? 5 + p_stream->fmt.i_extra : 0;
 696 
 697     esds = box_full_new("esds", 0, 0);
 698 
 699     /* ES_Descr */
 700     bo_add_descr(esds, 0x03, 3 + 5 + 13 + i_decoder_specific_info_size + 5 + 1);
 701     bo_add_16be(esds, p_stream->i_track_id);
 702     bo_add_8   (esds, 0x1f);      // flags=0|streamPriority=0x1f
 703 
 704     /* DecoderConfigDescr */
 705     bo_add_descr(esds, 0x04, 13 + i_decoder_specific_info_size);
 706 
 707     int  i_object_type_indication;
 708     switch(p_stream->fmt.i_codec)
 709     {
 710     case VLC_CODEC_MP4V:
 711         i_object_type_indication = 0x20;
 712         break;
 713     case VLC_CODEC_MP2V:
 714         /* MPEG-I=0x6b, MPEG-II = 0x60 -> 0x65 */
 715         i_object_type_indication = 0x65;
 716         break;
 717     case VLC_CODEC_MP1V:
 718         /* MPEG-I=0x6b, MPEG-II = 0x60 -> 0x65 */
 719         i_object_type_indication = 0x6b;
 720         break;
 721     case VLC_CODEC_MP4A:
 722         /* FIXME for mpeg2-aac == 0x66->0x68 */
 723         i_object_type_indication = 0x40;
 724         break;
 725     case VLC_CODEC_MPGA:
 726         i_object_type_indication =
 727             p_stream->fmt.audio.i_rate < 32000 ? 0x69 : 0x6b;
 728         break;
 729     default:
 730         i_object_type_indication = 0x00;
 731         break;
 732     }
 733     int i_stream_type = p_stream->fmt.i_cat == VIDEO_ES ? 0x04 : 0x05;
 734 
 735     bo_add_8   (esds, i_object_type_indication);
 736     bo_add_8   (esds, (i_stream_type << 2) | 1);
 737     bo_add_24be(esds, 1024 * 1024);       // bufferSizeDB
 738     bo_add_32be(esds, i_bitrate_max);     // maxBitrate
 739     bo_add_32be(esds, i_bitrate_avg);     // avgBitrate
 740 
 741     if (p_stream->fmt.i_extra > 0) {
 742         /* DecoderSpecificInfo */
 743         bo_add_descr(esds, 0x05, p_stream->fmt.i_extra);
 744 
 745         for (int i = 0; i < p_stream->fmt.i_extra; i++)
 746             bo_add_8(esds, ((uint8_t*)p_stream->fmt.p_extra)[i]);
 747     }
 748 
 749     /* SL_Descr mandatory */
 750     bo_add_descr(esds, 0x06, 1);
 751     bo_add_8    (esds, 0x02);  // sl_predefined
 752 
 753     return esds;
 754 }
 755 
 756 static bo_t *GetWaveTag(mp4_stream_t *p_stream)
 757 {
 758     bo_t *wave;
 759     bo_t *box;
 760 
 761     wave = box_new("wave");
 762 
 763     box = box_new("frma");
 764     bo_add_fourcc(box, "mp4a");
 765     box_gather(wave, box);
 766 
 767     box = box_new("mp4a");
 768     bo_add_32be(box, 0);
 769     box_gather(wave, box);
 770 
 771     box = GetESDS(p_stream);
 772     box_gather(wave, box);
 773 
 774     box = box_new("srcq");
 775     bo_add_32be(box, 0x40);
 776     box_gather(wave, box);
 777 
 778     /* wazza ? */
 779     bo_add_32be(wave, 8); /* new empty box */
 780     bo_add_32be(wave, 0); /* box label */
 781 
 782     return wave;
 783 }
 784 
 785 static bo_t *GetDamrTag(mp4_stream_t *p_stream)
 786 {
 787     bo_t *damr;
 788 
 789     damr = box_new("damr");
 790 
 791     bo_add_fourcc(damr, "REFC");
 792     bo_add_8(damr, 0);
 793 
 794     if (p_stream->fmt.i_codec == VLC_CODEC_AMR_NB)
 795         bo_add_16be(damr, 0x81ff); /* Mode set (all modes for AMR_NB) */
 796     else
 797         bo_add_16be(damr, 0x83ff); /* Mode set (all modes for AMR_WB) */
 798     bo_add_16be(damr, 0x1); /* Mode change period (no restriction) */
 799 
 800     return damr;
 801 }
 802 
 803 static bo_t *GetD263Tag(void)
 804 {
 805     bo_t *d263;
 806 
 807     d263 = box_new("d263");
 808 
 809     bo_add_fourcc(d263, "VLC ");
 810     bo_add_16be(d263, 0xa);
 811     bo_add_8(d263, 0);
 812 
 813     return d263;
 814 }
 815 
 816 static void hevcParseVPS(uint8_t * p_buffer, size_t i_buffer, uint8_t *general,
 817                          uint8_t * numTemporalLayer, bool * temporalIdNested)
 818 {
 819     const size_t i_decoded_nal_size = 512;
 820     uint8_t p_dec_nal[i_decoded_nal_size];
 821     size_t i_size = (i_buffer < i_decoded_nal_size)?i_buffer:i_decoded_nal_size;
 822     nal_decode(p_buffer, p_dec_nal, i_size);
 823 
 824     /* first two bytes are the NAL header, 3rd and 4th are:
 825         vps_video_parameter_set_id(4)
 826         vps_reserved_3_2bis(2)
 827         vps_max_layers_minus1(6)
 828         vps_max_sub_layers_minus1(3)
 829         vps_temporal_id_nesting_flags
 830     */
 831     *numTemporalLayer =  ((p_dec_nal[3] & 0x0E) >> 1) + 1;
 832     *temporalIdNested = (bool)(p_dec_nal[3] & 0x01);
 833 
 834     /* 5th & 6th are reserved 0xffff */
 835     /* copy the first 12 bytes of profile tier */
 836     memcpy(general, &p_dec_nal[6], 12);
 837 }
 838 
 839 static void hevcParseSPS(uint8_t * p_buffer, size_t i_buffer, uint8_t * chroma_idc,
 840                          uint8_t *bit_depth_luma_minus8, uint8_t *bit_depth_chroma_minus8)
 841 {
 842     const size_t i_decoded_nal_size = 512;
 843     uint8_t p_dec_nal[i_decoded_nal_size];
 844     size_t i_size = (i_buffer < i_decoded_nal_size)?i_buffer-2:i_decoded_nal_size;
 845     nal_decode(p_buffer+2, p_dec_nal, i_size);
 846     bs_t bs;
 847     bs_init(&bs, p_dec_nal, i_size);
 848 
 849     /* skip vps id */
 850     bs_skip(&bs, 4);
 851     uint32_t sps_max_sublayer_minus1 = bs_read(&bs, 3);
 852 
 853     /* skip nesting flag */
 854     bs_skip(&bs, 1);
 855 
 856     hevc_skip_profile_tiers_level(&bs, sps_max_sublayer_minus1);
 857 
 858     /* skip sps id */
 859     (void) read_ue( &bs );
 860 
 861     *chroma_idc = read_ue(&bs);
 862     if (*chroma_idc == 3)
 863         bs_skip(&bs, 1);
 864 
 865     /* skip width and heigh */
 866     (void) read_ue( &bs );
 867     (void) read_ue( &bs );
 868 
 869     uint32_t conformance_window_flag = bs_read1(&bs);
 870     if (conformance_window_flag) {
 871         /* skip offsets*/
 872         (void) read_ue(&bs);
 873         (void) read_ue(&bs);
 874         (void) read_ue(&bs);
 875         (void) read_ue(&bs);
 876     }
 877     *bit_depth_luma_minus8 = read_ue(&bs);
 878     *bit_depth_chroma_minus8 = read_ue(&bs);
 879 }
 880 
 881 static bo_t *GetHvcCTag(mp4_stream_t *p_stream)
 882 {
 883     /* Generate hvcC box matching iso/iec 14496-15 3rd edition */
 884     bo_t *hvcC = box_new("hvcC");
 885     if(!p_stream->fmt.i_extra)
 886         return hvcC;
 887 
 888     struct nal {
 889         size_t i_buffer;
 890         uint8_t * p_buffer;
 891     };
 892 
 893     /* According to the specification HEVC stream can have
 894      * 16 vps id and an "unlimited" number of sps and pps id using ue(v) id*/
 895     struct nal p_vps[16], *p_sps = NULL, *p_pps = NULL, *p_sei = NULL,
 896                *p_nal = NULL;
 897     size_t i_vps = 0, i_sps = 0, i_pps = 0, i_sei = 0;
 898     uint8_t i_num_arrays = 0;
 899 
 900     uint8_t * p_buffer = p_stream->fmt.p_extra;
 901     size_t i_buffer = p_stream->fmt.i_extra;
 902 
 903     uint8_t general_configuration[12] = {0};
 904     uint8_t i_numTemporalLayer = 0;
 905     uint8_t i_chroma_idc = 1;
 906     uint8_t i_bit_depth_luma_minus8 = 0;
 907     uint8_t i_bit_depth_chroma_minus8 = 0;
 908     bool b_temporalIdNested = false;
 909 
 910     uint32_t cmp = 0xFFFFFFFF;
 911     while (i_buffer) {
 912         /* look for start code 0X0000001 */
 913         while (i_buffer) {
 914             cmp = (cmp << 8) | *p_buffer;
 915             if((cmp ^ UINT32_C(0x100)) <= UINT32_C(0xFF))
 916                 break;
 917             p_buffer++;
 918             i_buffer--;
 919         }
 920         if (p_nal)
 921             p_nal->i_buffer = p_buffer - p_nal->p_buffer - ((i_buffer)?3:0);
 922 
 923         switch (*p_buffer & 0x72) {
 924             /* VPS */
 925         case 0x40:
 926             p_nal = &p_vps[i_vps++];
 927             p_nal->p_buffer = p_buffer;
 928             /* Only keep the general profile from the first VPS
 929              * if there are several (this shouldn't happen so soon) */
 930             if (i_vps == 1) {
 931                 hevcParseVPS(p_buffer, i_buffer, general_configuration,
 932                              &i_numTemporalLayer, &b_temporalIdNested);
 933                 i_num_arrays++;
 934             }
 935             break;
 936             /* SPS */
 937         case 0x42: {
 938             struct nal * p_tmp =  realloc(p_sps, sizeof(struct nal) * (i_sps + 1));
 939             if (!p_tmp)
 940                 break;
 941             p_sps = p_tmp;
 942             p_nal = &p_sps[i_sps++];
 943             p_nal->p_buffer = p_buffer;
 944             if (i_sps == 1 && i_buffer > 15) {
 945                 /* Get Chroma_idc and bitdepths */
 946                 hevcParseSPS(p_buffer, i_buffer, &i_chroma_idc,
 947                              &i_bit_depth_luma_minus8, &i_bit_depth_chroma_minus8);
 948                 i_num_arrays++;
 949             }
 950             break;
 951             }
 952         /* PPS */
 953         case 0x44: {
 954             struct nal * p_tmp =  realloc(p_pps, sizeof(struct nal) * (i_pps + 1));
 955             if (!p_tmp)
 956                 break;
 957             p_pps = p_tmp;
 958             p_nal = &p_pps[i_pps++];
 959             p_nal->p_buffer = p_buffer;
 960             if (i_pps == 1)
 961                 i_num_arrays++;
 962             break;
 963             }
 964         /* SEI */
 965         case 0x4E:
 966         case 0x50: {
 967             struct nal * p_tmp =  realloc(p_sei, sizeof(struct nal) * (i_sei + 1));
 968             if (!p_tmp)
 969                 break;
 970             p_sei = p_tmp;
 971             p_nal = &p_sei[i_sei++];
 972             p_nal->p_buffer = p_buffer;
 973             if(i_sei == 1)
 974                 i_num_arrays++;
 975             break;
 976         }
 977         default:
 978             p_nal = NULL;
 979             break;
 980         }
 981     }
 982     bo_add_8(hvcC, 0x01);
 983     bo_add_mem(hvcC, 12, general_configuration);
 984     /* Don't set min spatial segmentation */
 985     bo_add_16be(hvcC, 0xF000);
 986     /* Don't set parallelism type since segmentation isn't set */
 987     bo_add_8(hvcC, 0xFC);
 988     bo_add_8(hvcC, (0xFC | (i_chroma_idc & 0x03)));
 989     bo_add_8(hvcC, (0xF8 | (i_bit_depth_luma_minus8 & 0x07)));
 990     bo_add_8(hvcC, (0xF8 | (i_bit_depth_chroma_minus8 & 0x07)));
 991 
 992     /* Don't set framerate */
 993     bo_add_16be(hvcC, 0x0000);
 994     /* Force NAL size of 4 bytes that replace the startcode */
 995     bo_add_8(hvcC, (((i_numTemporalLayer & 0x07) << 3) |
 996                     (b_temporalIdNested << 2) | 0x03));
 997     bo_add_8(hvcC, i_num_arrays);
 998 
 999     if (i_vps)
1000     {
1001         /* Write VPS without forcing array_completeness */
1002         bo_add_8(hvcC, 32);
1003         bo_add_16be(hvcC, i_vps);
1004         for (size_t i = 0; i < i_vps; i++) {
1005             p_nal = &p_vps[i];
1006             bo_add_16be(hvcC, p_nal->i_buffer);
1007             bo_add_mem(hvcC, p_nal->i_buffer, p_nal->p_buffer);
1008         }
1009     }
1010 
1011     if (i_sps) {
1012         /* Write SPS without forcing array_completeness */
1013         bo_add_8(hvcC, 33);
1014         bo_add_16be(hvcC, i_sps);
1015         for (size_t i = 0; i < i_sps; i++) {
1016             p_nal = &p_sps[i];
1017             bo_add_16be(hvcC, p_nal->i_buffer);
1018             bo_add_mem(hvcC, p_nal->i_buffer, p_nal->p_buffer);
1019         }
1020     }
1021 
1022     if (i_pps) {
1023         /* Write PPS without forcing array_completeness */
1024         bo_add_8(hvcC, 34);
1025         bo_add_16be(hvcC, i_pps);
1026         for (size_t i = 0; i < i_pps; i++) {
1027             p_nal = &p_pps[i];
1028             bo_add_16be(hvcC, p_nal->i_buffer);
1029             bo_add_mem(hvcC, p_nal->i_buffer, p_nal->p_buffer);
1030         }
1031     }
1032 
1033     if (i_sei) {
1034         /* Write SEI without forcing array_completeness */
1035         bo_add_8(hvcC, 39);
1036         bo_add_16be(hvcC, i_sei);
1037         for (size_t i = 0; i < i_sei; i++) {
1038             p_nal = &p_sei[i];
1039             bo_add_16be(hvcC, p_nal->i_buffer);
1040             bo_add_mem(hvcC, p_nal->i_buffer, p_nal->p_buffer);
1041         }
1042     }
1043     return hvcC;
1044 }
1045 
1046 static bo_t *GetAvcCTag(mp4_stream_t *p_stream)
1047 {
1048     bo_t    *avcC = NULL;
1049     uint8_t *p_sps = NULL;
1050     uint8_t *p_pps = NULL;
1051     int     i_sps_size = 0;
1052     int     i_pps_size = 0;
1053 
1054     if (p_stream->fmt.i_extra > 0) {
1055         /* FIXME: take into account multiple sps/pps */
1056         uint8_t *p_buffer = p_stream->fmt.p_extra;
1057         int     i_buffer = p_stream->fmt.i_extra;
1058 
1059         while (i_buffer > 3) {
1060             while (memcmp(p_buffer, &avc1_start_code[1], 3)) {
1061                  i_buffer--;
1062                  p_buffer++;
1063             }
1064             const int i_nal_type = p_buffer[3]&0x1f;
1065             int i_startcode = 0;
1066  
1067             for (int i_offset = 1; i_offset+2 < i_buffer ; i_offset++)
1068                 if (!memcmp(&p_buffer[i_offset], &avc1_start_code[1], 3)) {
1069                     /* we found another startcode */
1070                     i_startcode = i_offset;
1071                     while (p_buffer[i_startcode-1] == 0 && i_startcode > 0)
1072                         i_startcode--;
1073                     break;
1074                 }
1075 
1076             int i_size = i_startcode ? i_startcode : i_buffer;
1077 
1078             if (i_nal_type == 7) {
1079                 p_sps = &p_buffer[3];
1080                 i_sps_size = i_size - 3;
1081             }
1082             if (i_nal_type == 8) {
1083                 p_pps = &p_buffer[3];
1084                 i_pps_size = i_size - 3;
1085             }
1086             i_buffer -= i_size;
1087             p_buffer += i_size;
1088         }
1089     }
1090  
1091     /* FIXME use better value */
1092     avcC = box_new("avcC");
1093     bo_add_8(avcC, 1);      /* configuration version */
1094     bo_add_8(avcC, i_sps_size ? p_sps[1] : 77);
1095     bo_add_8(avcC, i_sps_size ? p_sps[2] : 64);
1096     bo_add_8(avcC, i_sps_size ? p_sps[3] : 30);       /* level, 5.1 */
1097     bo_add_8(avcC, 0xff);   /* 0b11111100 | lengthsize = 0x11 */
1098 
1099     bo_add_8(avcC, 0xe0 | (i_sps_size > 0 ? 1 : 0));   /* 0b11100000 | sps_count */
1100     if (i_sps_size > 0) {
1101         bo_add_16be(avcC, i_sps_size);
1102         bo_add_mem(avcC, i_sps_size, p_sps);
1103     }
1104 
1105     bo_add_8(avcC, (i_pps_size > 0 ? 1 : 0));   /* pps_count */
1106     if (i_pps_size > 0) {
1107         bo_add_16be(avcC, i_pps_size);
1108         bo_add_mem(avcC, i_pps_size, p_pps);
1109     }
1110 
1111     return avcC;
1112 }
1113 
1114 /* TODO: No idea about these values */
1115 static bo_t *GetSVQ3Tag(mp4_stream_t *p_stream)
1116 {
1117     bo_t *smi = box_new("SMI ");
1118 
1119     if (p_stream->fmt.i_extra > 0x4e) {
1120         uint8_t *p_end = &((uint8_t*)p_stream->fmt.p_extra)[p_stream->fmt.i_extra];
1121         uint8_t *p     = &((uint8_t*)p_stream->fmt.p_extra)[0x46];
1122 
1123         while (p + 8 < p_end) {
1124             int i_size = GetDWBE(p);
1125             if (i_size <= 1) /* FIXME handle 1 as long size */
1126                 break;
1127             if (!strncmp((const char *)&p[4], "SMI ", 4)) {
1128                 bo_add_mem(smi, p_end - p - 8, &p[8]);
1129                 return smi;
1130             }
1131             p += i_size;
1132         }
1133     }
1134 
1135     /* Create a dummy one in fallback */
1136     bo_add_fourcc(smi, "SEQH");
1137     bo_add_32be(smi, 0x5);
1138     bo_add_32be(smi, 0xe2c0211d);
1139     bo_add_8(smi, 0xc0);
1140 
1141     return smi;
1142 }
1143 
1144 static bo_t *GetUdtaTag(sout_mux_t *p_mux)
1145 {
1146     sout_mux_sys_t *p_sys = p_mux->p_sys;
1147     bo_t *udta = box_new("udta");
1148 
1149     /* Requirements */
1150     for (unsigned int i_track = 0; i_track < p_sys->i_nb_streams; i_track++) {
1151         mp4_stream_t *p_stream = p_sys->pp_streams[i_track];
1152         vlc_fourcc_t codec = p_stream->fmt.i_codec;
1153 
1154         if (codec == VLC_CODEC_MP4V || codec == VLC_CODEC_MP4A) {
1155             bo_t *box = box_new("\251req");
1156             /* String length */
1157             bo_add_16be(box, sizeof("QuickTime 6.0 or greater") - 1);
1158             bo_add_16be(box, 0);
1159             bo_add_mem(box, sizeof("QuickTime 6.0 or greater") - 1,
1160                         (uint8_t *)"QuickTime 6.0 or greater");
1161             box_gather(udta, box);
1162             break;
1163         }
1164     }
1165 
1166     /* Encoder */
1167     {
1168         bo_t *box = box_new("\251enc");
1169         /* String length */
1170         bo_add_16be(box, sizeof(PACKAGE_STRING " stream output") - 1);
1171         bo_add_16be(box, 0);
1172         bo_add_mem(box, sizeof(PACKAGE_STRING " stream output") - 1,
1173                     (uint8_t*)PACKAGE_STRING " stream output");
1174         box_gather(udta, box);
1175     }
1176 #if 0
1177     /* Misc atoms */
1178     vlc_meta_t *p_meta = p_mux->p_sout->p_meta;
1179     if (p_meta) {
1180 #define ADD_META_BOX(type, box_string) { \
1181         bo_t *box = NULL;  \
1182         if (vlc_meta_Get(p_meta, vlc_meta_##type)) \
1183             box = box_new("\251" box_string); \
1184         if (box) { \
1185             bo_add_16be(box, strlen(vlc_meta_Get(p_meta, vlc_meta_##type))); \
1186             bo_add_16be(box, 0); \
1187             bo_add_mem(box, strlen(vlc_meta_Get(p_meta, vlc_meta_##type)), \
1188                         (uint8_t*)(vlc_meta_Get(p_meta, vlc_meta_##type))); \
1189             box_gather(udta, box); \
1190         } }
1191 
1192         ADD_META_BOX(Title, "nam");
1193         ADD_META_BOX(Artist, "ART");
1194         ADD_META_BOX(Genre, "gen");
1195         ADD_META_BOX(Copyright, "cpy");
1196         ADD_META_BOX(Description, "des");
1197         ADD_META_BOX(Date, "day");
1198         ADD_META_BOX(URL, "url");
1199 #undef ADD_META_BOX
1200     }
1201 #endif
1202     return udta;
1203 }
1204 
1205 static bo_t *GetSounBox(sout_mux_t *p_mux, mp4_stream_t *p_stream)
1206 {
1207     sout_mux_sys_t *p_sys = p_mux->p_sys;
1208     bool b_descr = true;
1209     vlc_fourcc_t codec = p_stream->fmt.i_codec;
1210     char fcc[4];
1211     vlc_fourcc_to_char(codec, fcc);
1212 
1213     if (codec == VLC_CODEC_MPGA) {
1214         if (p_sys->b_mov) {
1215             b_descr = false;
1216             memcpy(fcc, ".mp3", 4);
1217         } else
1218             memcpy(fcc, "mp4a", 4);
1219     }
1220 
1221     bo_t *soun = box_new(fcc);
1222     for (int i = 0; i < 6; i++)
1223         bo_add_8(soun, 0);        // reserved;
1224     bo_add_16be(soun, 1);         // data-reference-index
1225 
1226     /* SoundDescription */
1227     if (p_sys->b_mov && codec == VLC_CODEC_MP4A)
1228         bo_add_16be(soun, 1);     // version 1;
1229     else
1230         bo_add_16be(soun, 0);     // version 0;
1231     bo_add_16be(soun, 0);         // revision level (0)
1232     bo_add_32be(soun, 0);         // vendor
1233     // channel-count
1234     bo_add_16be(soun, p_stream->fmt.audio.i_channels);
1235     // sample size
1236     bo_add_16be(soun, p_stream->fmt.audio.i_bitspersample ?
1237                  p_stream->fmt.audio.i_bitspersample : 16);
1238     bo_add_16be(soun, -2);        // compression id
1239     bo_add_16be(soun, 0);         // packet size (0)
1240     bo_add_16be(soun, p_stream->fmt.audio.i_rate); // sampleratehi
1241     bo_add_16be(soun, 0);                             // sampleratelo
1242 
1243     /* Extended data for SoundDescription V1 */
1244     if (p_sys->b_mov && p_stream->fmt.i_codec == VLC_CODEC_MP4A) {
1245         /* samples per packet */
1246         bo_add_32be(soun, p_stream->fmt.audio.i_frame_length);
1247         bo_add_32be(soun, 1536); /* bytes per packet */
1248         bo_add_32be(soun, 2);    /* bytes per frame */
1249         /* bytes per sample */
1250         bo_add_32be(soun, 2 /*p_stream->fmt.audio.i_bitspersample/8 */);
1251     }
1252 
1253     /* Add an ES Descriptor */
1254     if (b_descr) {
1255         bo_t *box;
1256 
1257         if (p_sys->b_mov && codec == VLC_CODEC_MP4A)
1258             box = GetWaveTag(p_stream);
1259         else if (codec == VLC_CODEC_AMR_NB)
1260             box = GetDamrTag(p_stream);
1261         else
1262             box = GetESDS(p_stream);
1263         box_gather(soun, box);
1264     }
1265 
1266     return soun;
1267 }
1268 
1269 static bo_t *GetVideBox(mp4_stream_t *p_stream)
1270 {
1271     char fcc[4];
1272 
1273     switch(p_stream->fmt.i_codec)
1274     {
1275     case VLC_CODEC_MP4V:
1276     case VLC_CODEC_MPGV: memcpy(fcc, "mp4v", 4); break;
1277     case VLC_CODEC_MJPG: memcpy(fcc, "mjpa", 4); break;
1278     case VLC_CODEC_SVQ1: memcpy(fcc, "SVQ1", 4); break;
1279     case VLC_CODEC_SVQ3: memcpy(fcc, "SVQ3", 4); break;
1280     case VLC_CODEC_H263: memcpy(fcc, "s263", 4); break;
1281     case VLC_CODEC_H264: memcpy(fcc, "avc1", 4); break;
1282     case VLC_CODEC_HEVC: memcpy(fcc, "hvc1", 4); break;
1283     case VLC_CODEC_YV12: memcpy(fcc, "yv12", 4); break;
1284     case VLC_CODEC_YUYV: memcpy(fcc, "yuy2", 4); break;
1285     default:
1286         vlc_fourcc_to_char(p_stream->fmt.i_codec, fcc);
1287         break;
1288     }
1289 
1290     bo_t *vide = box_new(fcc);
1291     for (int i = 0; i < 6; i++)
1292         bo_add_8(vide, 0);        // reserved;
1293     bo_add_16be(vide, 1);         // data-reference-index
1294 
1295     bo_add_16be(vide, 0);         // predefined;
1296     bo_add_16be(vide, 0);         // reserved;
1297     for (int i = 0; i < 3; i++)
1298         bo_add_32be(vide, 0);     // predefined;
1299 
1300     bo_add_16be(vide, p_stream->fmt.video.i_width);  // i_width
1301     bo_add_16be(vide, p_stream->fmt.video.i_height); // i_height
1302 
1303     bo_add_32be(vide, 0x00480000);                // h 72dpi
1304     bo_add_32be(vide, 0x00480000);                // v 72dpi
1305 
1306     bo_add_32be(vide, 0);         // data size, always 0
1307     bo_add_16be(vide, 1);         // frames count per sample
1308 
1309     // compressor name;
1310     for (int i = 0; i < 32; i++)
1311         bo_add_8(vide, 0);
1312 
1313     bo_add_16be(vide, 0x18);      // depth
1314     bo_add_16be(vide, 0xffff);    // predefined
1315 
1316     /* add an ES Descriptor */
1317     switch(p_stream->fmt.i_codec)
1318     {
1319     case VLC_CODEC_MP4V:
1320     case VLC_CODEC_MPGV:
1321         box_gather(vide, GetESDS(p_stream));
1322         break;
1323 
1324     case VLC_CODEC_H263:
1325         box_gather(vide, GetD263Tag());
1326         break;
1327 
1328     case VLC_CODEC_SVQ3:
1329         box_gather(vide, GetSVQ3Tag(p_stream));
1330         break;
1331 
1332     case VLC_CODEC_H264:
1333         box_gather(vide, GetAvcCTag(p_stream));
1334         break;
1335 
1336     case VLC_CODEC_HEVC:
1337         box_gather(vide, GetHvcCTag(p_stream));
1338         break;
1339     }
1340 
1341     return vide;
1342 }
1343 
1344 static bo_t *GetTextBox(void)
1345 {
1346     bo_t *text = box_new("text");
1347 
1348     for (int i = 0; i < 6; i++)
1349         bo_add_8(text, 0);        // reserved;
1350     bo_add_16be(text, 1);         // data-reference-index
1351 
1352     bo_add_32be(text, 0);         // display flags
1353     bo_add_32be(text, 0);         // justification
1354     for (int i = 0; i < 3; i++)
1355         bo_add_16be(text, 0);     // back ground color
1356 
1357     bo_add_16be(text, 0);         // box text
1358     bo_add_16be(text, 0);         // box text
1359     bo_add_16be(text, 0);         // box text
1360     bo_add_16be(text, 0);         // box text
1361 
1362     bo_add_64be(text, 0);         // reserved
1363     for (int i = 0; i < 3; i++)
1364         bo_add_16be(text, 0xff);  // foreground color
1365 
1366     bo_add_8 (text, 9);
1367     bo_add_mem(text, 9, (uint8_t*)"Helvetica");
1368 
1369     return text;
1370 }
1371 
1372 static bo_t *GetStblBox(sout_mux_t *p_mux, mp4_stream_t *p_stream)
1373 {
1374     sout_mux_sys_t *p_sys = p_mux->p_sys;
1375 
1376     /* sample description */
1377     bo_t *stsd = box_full_new("stsd", 0, 0);
1378     bo_add_32be(stsd, 1);
1379     if (p_stream->fmt.i_cat == AUDIO_ES)
1380         box_gather(stsd, GetSounBox(p_mux, p_stream));
1381     else if (p_stream->fmt.i_cat == VIDEO_ES)
1382         box_gather(stsd, GetVideBox(p_stream));
1383     else if (p_stream->fmt.i_cat == SPU_ES)
1384         box_gather(stsd, GetTextBox());
1385 
1386     /* chunk offset table */
1387     bo_t *stco;
1388     if (p_sys->i_pos >= (((uint64_t)0x1) << 32)) {
1389         /* 64 bits version */
1390         p_stream->b_stco64 = true;
1391         stco = box_full_new("co64", 0, 0);
1392     } else {
1393         /* 32 bits version */
1394         p_stream->b_stco64 = false;
1395         stco = box_full_new("stco", 0, 0);
1396     }
1397     bo_add_32be(stco, 0);     // entry-count (fixed latter)
1398 
1399     /* sample to chunk table */
1400     bo_t *stsc = box_full_new("stsc", 0, 0);
1401     bo_add_32be(stsc, 0);     // entry-count (fixed latter)
1402 
1403     unsigned i_chunk = 0;
1404     unsigned i_stsc_last_val = 0, i_stsc_entries = 0;
1405     for (unsigned i = 0; i < p_stream->i_entry_count; i_chunk++) {
1406         mp4_entry_t *entry = p_stream->entry;
1407         int i_first = i;
1408 
1409         if (p_stream->b_stco64)
1410             bo_add_64be(stco, entry[i].i_pos);
1411         else
1412             bo_add_32be(stco, entry[i].i_pos);
1413 
1414         for (; i < p_stream->i_entry_count; i++)
1415             if (i >= p_stream->i_entry_count - 1 ||
1416                     entry[i].i_pos + entry[i].i_size != entry[i+1].i_pos) {
1417                 i++;
1418                 break;
1419             }
1420 
1421         /* Add entry to the stsc table */
1422         if (i_stsc_last_val != i - i_first) {
1423             bo_add_32be(stsc, 1 + i_chunk);   // first-chunk
1424             bo_add_32be(stsc, i - i_first) ;  // samples-per-chunk
1425             bo_add_32be(stsc, 1);             // sample-descr-index
1426             i_stsc_last_val = i - i_first;
1427             i_stsc_entries++;
1428         }
1429     }
1430 
1431     /* Fix stco entry count */
1432     bo_fix_32be(stco, 12, i_chunk);
1433     msg_Dbg(p_mux, "created %d chunks (stco)", i_chunk);
1434 
1435     /* Fix stsc entry count */
1436     bo_fix_32be(stsc, 12, i_stsc_entries );
1437 
1438     /* add stts */
1439     bo_t *stts = box_full_new("stts", 0, 0);
1440     bo_add_32be(stts, 0);     // entry-count (fixed latter)
1441 
1442     unsigned i_index = 0;
1443     for (unsigned i = 0; i < p_stream->i_entry_count; i_index++) {
1444         int     i_first = i;
1445         mtime_t i_delta = p_stream->entry[i].i_length;
1446 
1447         for (; i < p_stream->i_entry_count; ++i)
1448             if (i == p_stream->i_entry_count || p_stream->entry[i].i_length != i_delta)
1449                 break;
1450 
1451         bo_add_32be(stts, i - i_first); // sample-count
1452         bo_add_32be(stts, i_delta * p_stream->i_timescale / CLOCK_FREQ ); // sample-delta
1453     }
1454     bo_fix_32be(stts, 12, i_index);
1455 
1456     /* composition time handling */
1457     bo_t *ctts = NULL;
1458     if ( p_stream->b_hasbframes && (ctts = box_full_new("ctts", 0, 0)) )
1459     {
1460         bo_add_32be(ctts, 0);
1461         i_index = 0;
1462         for (unsigned i = 0; i < p_stream->i_entry_count; i_index++)
1463         {
1464             int     i_first = i;
1465             mtime_t i_offset = p_stream->entry[i].i_pts_dts;
1466 
1467             for (; i < p_stream->i_entry_count; ++i)
1468                 if (i == p_stream->i_entry_count || p_stream->entry[i].i_pts_dts != i_offset)
1469                     break;
1470 
1471             bo_add_32be(ctts, i - i_first); // sample-count
1472             bo_add_32be(ctts, i_offset * p_stream->i_timescale / CLOCK_FREQ ); // sample-offset
1473         }
1474         bo_fix_32be(ctts, 12, i_index);
1475     }
1476 
1477     bo_t *stsz = box_full_new("stsz", 0, 0);
1478     int i_size = 0;
1479     for (unsigned i = 0; i < p_stream->i_entry_count; i++)
1480     {
1481         if ( i == 0 )
1482             i_size = p_stream->entry[i].i_size;
1483         else if ( p_stream->entry[i].i_size != i_size )
1484         {
1485             i_size = 0;
1486             break;
1487         }
1488     }
1489     bo_add_32be(stsz, i_size);                         // sample-size
1490     bo_add_32be(stsz, p_stream->i_entry_count);       // sample-count
1491     if ( i_size == 0 ) // all samples have different size
1492     {
1493         for (unsigned i = 0; i < p_stream->i_entry_count; i++)
1494             bo_add_32be(stsz, p_stream->entry[i].i_size); // sample-size
1495     }
1496 
1497     /* create stss table */
1498     bo_t *stss = NULL;
1499     i_index = 0;
1500     if ( p_stream->fmt.i_cat == VIDEO_ES || p_stream->fmt.i_cat == AUDIO_ES )
1501     {
1502         mtime_t i_interval = -1;
1503         for (unsigned i = 0; i < p_stream->i_entry_count; i++)
1504         {
1505             if ( i_interval != -1 )
1506             {
1507                 i_interval += p_stream->entry[i].i_length + p_stream->entry[i].i_pts_dts;
1508                 if ( i_interval < CLOCK_FREQ * 2 )
1509                     continue;
1510             }
1511 
1512             if (p_stream->entry[i].i_flags & BLOCK_FLAG_TYPE_I) {
1513                 if (stss == NULL) {
1514                     stss = box_full_new("stss", 0, 0);
1515                     bo_add_32be(stss, 0); /* fixed later */
1516                 }
1517                 bo_add_32be(stss, 1 + i);
1518                 i_index++;
1519                 i_interval = 0;
1520             }
1521         }
1522     }
1523 
1524     if (stss)
1525         bo_fix_32be(stss, 12, i_index);
1526 
1527     /* Now gather all boxes into stbl */
1528     bo_t *stbl = box_new("stbl");
1529 
1530     box_gather(stbl, stsd);
1531     box_gather(stbl, stts);
1532     if (stss)
1533         box_gather(stbl, stss);
1534     if (ctts)
1535         box_gather(stbl, ctts);
1536     box_gather(stbl, stsc);
1537     box_gather(stbl, stsz);
1538     p_stream->i_stco_pos = stbl->len + 16;
1539     box_gather(stbl, stco);
1540 
1541     return stbl;
1542 }
1543 
1544 static int64_t get_timestamp(void);
1545 
1546 static void matrix_apply_rotation(es_format_t *fmt, uint32_t mvhd_matrix[9])
1547 {
1548     enum video_orientation_t orientation = ORIENT_NORMAL;
1549     if (fmt->i_cat == VIDEO_ES)
1550         orientation = fmt->video.orientation;
1551 
1552 #define ATAN(a, b) do { mvhd_matrix[1] = (a) << 16; \
1553     mvhd_matrix[0] = (b) << 16; \
1554     } while(0)
1555 
1556     switch (orientation) {
1557     case ORIENT_ROTATED_90:  ATAN( 1,  0); break;
1558     case ORIENT_ROTATED_180: ATAN( 0, -1); break;
1559     case ORIENT_ROTATED_270: ATAN( -1, 0); break;
1560     default:                 ATAN( 0,  1); break;
1561     }
1562 
1563     mvhd_matrix[3] = mvhd_matrix[0] ? 0 : 0x10000;
1564     mvhd_matrix[4] = mvhd_matrix[1] ? 0 : 0x10000;
1565 }
1566 
1567 static bo_t *GetMoovBox(sout_mux_t *p_mux)
1568 {
1569     sout_mux_sys_t *p_sys = p_mux->p_sys;
1570 
1571     bo_t            *moov, *mvhd;
1572 
1573     uint32_t        i_movie_timescale = 90000;
1574     int64_t         i_movie_duration  = 0;
1575     int64_t         i_timestamp = get_timestamp();
1576 
1577     moov = box_new("moov");
1578 
1579     /* Create general info */
1580     for (unsigned int i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++) {
1581         mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
1582         i_movie_duration = __MAX(i_movie_duration, p_stream->i_duration);
1583     }
1584     msg_Dbg(p_mux, "movie duration %"PRId64"s", i_movie_duration / CLOCK_FREQ);
1585 
1586     i_movie_duration = i_movie_duration * i_movie_timescale / CLOCK_FREQ;
1587 
1588     /* *** add /moov/mvhd *** */
1589     if (!p_sys->b_64_ext) {
1590         mvhd = box_full_new("mvhd", 0, 0);
1591         bo_add_32be(mvhd, i_timestamp);   // creation time
1592         bo_add_32be(mvhd, i_timestamp);   // modification time
1593         bo_add_32be(mvhd, i_movie_timescale);  // timescale
1594         bo_add_32be(mvhd, i_movie_duration);  // duration
1595     } else {
1596         mvhd = box_full_new("mvhd", 1, 0);
1597         bo_add_64be(mvhd, i_timestamp);   // creation time
1598         bo_add_64be(mvhd, i_timestamp);   // modification time
1599         bo_add_32be(mvhd, i_movie_timescale);  // timescale
1600         bo_add_64be(mvhd, i_movie_duration);  // duration
1601     }
1602     bo_add_32be(mvhd, 0x10000);           // rate
1603     bo_add_16be(mvhd, 0x100);             // volume
1604     bo_add_16be(mvhd, 0);                 // reserved
1605     for (int i = 0; i < 2; i++)
1606         bo_add_32be(mvhd, 0);             // reserved
1607 
1608     uint32_t mvhd_matrix[9] = { 0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000 };
1609 
1610     for (int i = 0; i < 9; i++)
1611         bo_add_32be(mvhd, mvhd_matrix[i]);// matrix
1612     for (int i = 0; i < 6; i++)
1613         bo_add_32be(mvhd, 0);             // pre-defined
1614 
1615     /* Next available track id */
1616     bo_add_32be(mvhd, p_sys->i_nb_streams + 1); // next-track-id
1617 
1618     box_gather(moov, mvhd);
1619 
1620     for (unsigned int i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++) {
1621         mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
1622 
1623         /* *** add /moov/trak *** */
1624         bo_t *trak = box_new("trak");
1625 
1626         /* *** add /moov/trak/tkhd *** */
1627         bo_t *tkhd;
1628         if (!p_sys->b_64_ext) {
1629             if (p_sys->b_mov)
1630                 tkhd = box_full_new("tkhd", 0, 0x0f);
1631             else
1632                 tkhd = box_full_new("tkhd", 0, 1);
1633 
1634             bo_add_32be(tkhd, i_timestamp);       // creation time
1635             bo_add_32be(tkhd, i_timestamp);       // modification time
1636             bo_add_32be(tkhd, p_stream->i_track_id);
1637             bo_add_32be(tkhd, 0);                     // reserved 0
1638             bo_add_32be(tkhd, p_stream->i_duration *
1639                          (int64_t)i_movie_timescale / CLOCK_FREQ); // duration
1640         } else {
1641             if (p_sys->b_mov)
1642                 tkhd = box_full_new("tkhd", 1, 0x0f);
1643             else
1644                 tkhd = box_full_new("tkhd", 1, 1);
1645 
1646             bo_add_64be(tkhd, i_timestamp);       // creation time
1647             bo_add_64be(tkhd, i_timestamp);       // modification time
1648             bo_add_32be(tkhd, p_stream->i_track_id);
1649             bo_add_32be(tkhd, 0);                     // reserved 0
1650             bo_add_64be(tkhd, p_stream->i_duration *
1651                          (int64_t)i_movie_timescale / CLOCK_FREQ); // duration
1652         }
1653 
1654         for (int i = 0; i < 2; i++)
1655             bo_add_32be(tkhd, 0);                 // reserved
1656         bo_add_16be(tkhd, 0);                     // layer
1657         bo_add_16be(tkhd, 0);                     // pre-defined
1658         // volume
1659         bo_add_16be(tkhd, p_stream->fmt.i_cat == AUDIO_ES ? 0x100 : 0);
1660         bo_add_16be(tkhd, 0);                     // reserved
1661         matrix_apply_rotation(&p_stream->fmt, mvhd_matrix);
1662         for (int i = 0; i < 9; i++)
1663             bo_add_32be(tkhd, mvhd_matrix[i]);    // matrix
1664         if (p_stream->fmt.i_cat == AUDIO_ES) {
1665             bo_add_32be(tkhd, 0);                 // width (presentation)
1666             bo_add_32be(tkhd, 0);                 // height(presentation)
1667         } else if (p_stream->fmt.i_cat == VIDEO_ES) {
1668             int i_width = p_stream->fmt.video.i_width << 16;
1669             if (p_stream->fmt.video.i_sar_num > 0 && p_stream->fmt.video.i_sar_den > 0) {
1670                 i_width = (int64_t)p_stream->fmt.video.i_sar_num *
1671                           ((int64_t)p_stream->fmt.video.i_width << 16) /
1672                           p_stream->fmt.video.i_sar_den;
1673             }
1674             // width (presentation)
1675             bo_add_32be(tkhd, i_width);
1676             // height(presentation)
1677             bo_add_32be(tkhd, p_stream->fmt.video.i_height << 16);
1678         } else {
1679             int i_width = 320 << 16;
1680             int i_height = 200;
1681             for (unsigned int i = 0; i < p_sys->i_nb_streams; i++) {
1682                 mp4_stream_t *tk = p_sys->pp_streams[i];
1683                 if (tk->fmt.i_cat == VIDEO_ES) {
1684                     if (tk->fmt.video.i_sar_num > 0 &&
1685                         tk->fmt.video.i_sar_den > 0)
1686                         i_width = (int64_t)tk->fmt.video.i_sar_num *
1687                                   ((int64_t)tk->fmt.video.i_width << 16) /
1688                                   tk->fmt.video.i_sar_den;
1689                     else
1690                         i_width = tk->fmt.video.i_width << 16;
1691                     i_height = tk->fmt.video.i_height;
1692                     break;
1693                 }
1694             }
1695             bo_add_32be(tkhd, i_width);     // width (presentation)
1696             bo_add_32be(tkhd, i_height << 16);    // height(presentation)
1697         }
1698 
1699         box_gather(trak, tkhd);
1700 
1701         /* *** add /moov/trak/edts and elst */
1702         bo_t *edts = box_new("edts");
1703         bo_t *elst = box_full_new("elst", p_sys->b_64_ext ? 1 : 0, 0);
1704         if (p_stream->i_starttime > 0) {
1705             bo_add_32be(elst, 2);
1706 
1707             if (p_sys->b_64_ext) {
1708                 bo_add_64be(elst, p_stream->i_starttime *
1709                              i_movie_timescale / CLOCK_FREQ);
1710                 bo_add_64be(elst, -1);
1711             } else {
1712                 bo_add_32be(elst, p_stream->i_starttime *
1713                              i_movie_timescale / CLOCK_FREQ);
1714                 bo_add_32be(elst, -1);
1715             }
1716             bo_add_16be(elst, 1);
1717             bo_add_16be(elst, 0);
1718         } else {
1719             bo_add_32be(elst, 1);
1720         }
1721         if (p_sys->b_64_ext) {
1722             bo_add_64be(elst, p_stream->i_duration *
1723                          i_movie_timescale / CLOCK_FREQ);
1724             bo_add_64be(elst, 0);
1725         } else {
1726             bo_add_32be(elst, p_stream->i_duration *
1727                          i_movie_timescale / CLOCK_FREQ);
1728             bo_add_32be(elst, 0);
1729         }
1730         bo_add_16be(elst, 1);
1731         bo_add_16be(elst, 0);
1732 
1733         box_gather(edts, elst);
1734         box_gather(trak, edts);
1735 
1736         /* *** add /moov/trak/mdia *** */
1737         bo_t *mdia = box_new("mdia");
1738 
1739         /* media header */
1740         bo_t *mdhd;
1741         if (!p_sys->b_64_ext) {
1742             mdhd = box_full_new("mdhd", 0, 0);
1743             bo_add_32be(mdhd, i_timestamp);   // creation time
1744             bo_add_32be(mdhd, i_timestamp);   // modification time
1745             bo_add_32be(mdhd, p_stream->i_timescale); // timescale
1746             bo_add_32be(mdhd, p_stream->i_duration * (int64_t)p_stream->i_timescale /
1747                                CLOCK_FREQ);  // duration
1748         } else {
1749             mdhd = box_full_new("mdhd", 1, 0);
1750             bo_add_64be(mdhd, i_timestamp);   // creation time
1751             bo_add_64be(mdhd, i_timestamp);   // modification time
1752             bo_add_32be(mdhd, p_stream->i_timescale); // timescale
1753             bo_add_64be(mdhd, p_stream->i_duration * (int64_t)p_stream->i_timescale /
1754                                CLOCK_FREQ);  // duration
1755         }
1756 
1757         if (p_stream->fmt.psz_language) {
1758             char *psz = p_stream->fmt.psz_language;
1759             const iso639_lang_t *pl = NULL;
1760             uint16_t lang = 0x0;
1761 
1762             if (strlen(psz) == 2)
1763                 pl = GetLang_1(psz);
1764             else if (strlen(psz) == 3) {
1765                 pl = GetLang_2B(psz);
1766                 if (!strcmp(pl->psz_iso639_1, "??"))
1767                     pl = GetLang_2T(psz);
1768             }
1769 
1770             if (pl && strcmp(pl->psz_iso639_1, "??"))
1771                 lang = ((pl->psz_iso639_2T[0] - 0x60) << 10) |
1772                        ((pl->psz_iso639_2T[1] - 0x60) <<  5) |
1773                        ((pl->psz_iso639_2T[2] - 0x60));
1774             bo_add_16be(mdhd, lang);          // language
1775         } else
1776             bo_add_16be(mdhd, 0   );          // language
1777         bo_add_16be(mdhd, 0   );              // predefined
1778         box_gather(mdia, mdhd);
1779 
1780         /* handler reference */
1781         bo_t *hdlr = box_full_new("hdlr", 0, 0);
1782 
1783         if (p_sys->b_mov)
1784             bo_add_fourcc(hdlr, "mhlr");         // media handler
1785         else
1786             bo_add_32be(hdlr, 0);
1787 
1788         if (p_stream->fmt.i_cat == AUDIO_ES)
1789             bo_add_fourcc(hdlr, "soun");
1790         else if (p_stream->fmt.i_cat == VIDEO_ES)
1791             bo_add_fourcc(hdlr, "vide");
1792         else if (p_stream->fmt.i_cat == SPU_ES)
1793             bo_add_fourcc(hdlr, "text");
1794 
1795         bo_add_32be(hdlr, 0);         // reserved
1796         bo_add_32be(hdlr, 0);         // reserved
1797         bo_add_32be(hdlr, 0);         // reserved
1798 
1799         if (p_sys->b_mov)
1800             bo_add_8(hdlr, 12);   /* Pascal string for .mov */
1801 
1802         if (p_stream->fmt.i_cat == AUDIO_ES)
1803             bo_add_mem(hdlr, 12, (uint8_t*)"SoundHandler");
1804         else if (p_stream->fmt.i_cat == VIDEO_ES)
1805             bo_add_mem(hdlr, 12, (uint8_t*)"VideoHandler");
1806         else
1807             bo_add_mem(hdlr, 12, (uint8_t*)"Text Handler");
1808 
1809         if (!p_sys->b_mov)
1810             bo_add_8(hdlr, 0);   /* asciiz string for .mp4, yes that's BRAIN DAMAGED F**K MP4 */
1811 
1812         box_gather(mdia, hdlr);
1813 
1814         /* minf*/
1815         bo_t *minf = box_new("minf");
1816 
1817         /* add smhd|vmhd */
1818         if (p_stream->fmt.i_cat == AUDIO_ES) {
1819             bo_t *smhd;
1820 
1821             smhd = box_full_new("smhd", 0, 0);
1822             bo_add_16be(smhd, 0);     // balance
1823             bo_add_16be(smhd, 0);     // reserved
1824 
1825             box_gather(minf, smhd);
1826         } else if (p_stream->fmt.i_cat == VIDEO_ES) {
1827             bo_t *vmhd;
1828 
1829             vmhd = box_full_new("vmhd", 0, 1);
1830             bo_add_16be(vmhd, 0);     // graphicsmode
1831             for (int i = 0; i < 3; i++)
1832                 bo_add_16be(vmhd, 0); // opcolor
1833 
1834             box_gather(minf, vmhd);
1835         } else if (p_stream->fmt.i_cat == SPU_ES) {
1836             bo_t *gmhd = box_new("gmhd");
1837             bo_t *gmin = box_full_new("gmin", 0, 1);
1838 
1839             bo_add_16be(gmin, 0);     // graphicsmode
1840             for (int i = 0; i < 3; i++)
1841                 bo_add_16be(gmin, 0); // opcolor
1842             bo_add_16be(gmin, 0);     // balance
1843             bo_add_16be(gmin, 0);     // reserved
1844 
1845             box_gather(gmhd, gmin);
1846 
1847             box_gather(minf, gmhd);
1848         }
1849 
1850         /* dinf */
1851         bo_t *dinf = box_new("dinf");
1852         bo_t *dref = box_full_new("dref", 0, 0);
1853         bo_add_32be(dref, 1);
1854         bo_t *url = box_full_new("url ", 0, 0x01);
1855         box_gather(dref, url);
1856         box_gather(dinf, dref);
1857 
1858         /* append dinf to mdia */
1859         box_gather(minf, dinf);
1860 
1861         /* add stbl */
1862         bo_t *stbl = GetStblBox(p_mux, p_stream);
1863 
1864         /* append stbl to minf */
1865         p_stream->i_stco_pos += minf->len;
1866         box_gather(minf, stbl);
1867 
1868         /* append minf to mdia */
1869         p_stream->i_stco_pos += mdia->len;
1870         box_gather(mdia, minf);
1871 
1872         /* append mdia to trak */
1873         p_stream->i_stco_pos += trak->len;
1874         box_gather(trak, mdia);
1875 
1876         /* append trak to moov */
1877         p_stream->i_stco_pos += moov->len;
1878         box_gather(moov, trak);
1879     }
1880 
1881     /* Add user data tags */
1882     box_gather(moov, GetUdtaTag(p_mux));
1883 
1884     box_fix(moov);
1885     return moov;
1886 }
1887 
1888 /****************************************************************************/
1889 
1890 static void bo_init(bo_t *p_bo)
1891 {
1892     p_bo->len = 0;
1893     p_bo->b = block_Alloc(1024);
1894 }
1895 
1896 static void bo_add_8(bo_t *p_bo, uint8_t i)
1897 {
1898     if (p_bo->len >= p_bo->b->i_buffer)
1899         p_bo->b = block_Realloc(p_bo->b, 0, p_bo->b->i_buffer + 1024);
1900 
1901     p_bo->b->p_buffer[p_bo->len++] = i;
1902 }
1903 
1904 static void bo_add_16be(bo_t *p_bo, uint16_t i)
1905 {
1906     bo_add_8(p_bo, ((i >> 8) &0xff));
1907     bo_add_8(p_bo, i &0xff);
1908 }
1909 
1910 static void bo_add_24be(bo_t *p_bo, uint32_t i)
1911 {
1912     bo_add_8(p_bo, ((i >> 16) &0xff));
1913     bo_add_8(p_bo, ((i >> 8) &0xff));
1914     bo_add_8(p_bo, (  i &0xff));
1915 }
1916 static void bo_add_32be(bo_t *p_bo, uint32_t i)
1917 {
1918     bo_add_16be(p_bo, ((i >> 16) &0xffff));
1919     bo_add_16be(p_bo, i &0xffff);
1920 }
1921 
1922 static void bo_fix_32be (bo_t *p_bo, int i_pos, uint32_t i)
1923 {
1924     p_bo->b->p_buffer[i_pos    ] = (i >> 24)&0xff;
1925     p_bo->b->p_buffer[i_pos + 1] = (i >> 16)&0xff;
1926     p_bo->b->p_buffer[i_pos + 2] = (i >>  8)&0xff;
1927     p_bo->b->p_buffer[i_pos + 3] = (i      )&0xff;
1928 }
1929 
1930 static void bo_add_64be(bo_t *p_bo, uint64_t i)
1931 {
1932     bo_add_32be(p_bo, ((i >> 32) &0xffffffff));
1933     bo_add_32be(p_bo, i &0xffffffff);
1934 }
1935 
1936 static void bo_add_fourcc(bo_t *p_bo, const char *fcc)
1937 {
1938     bo_add_8(p_bo, fcc[0]);
1939     bo_add_8(p_bo, fcc[1]);
1940     bo_add_8(p_bo, fcc[2]);
1941     bo_add_8(p_bo, fcc[3]);
1942 }
1943 
1944 static void bo_add_mem(bo_t *p_bo, int i_size, uint8_t *p_mem)
1945 {
1946     for (int i = 0; i < i_size; i++)
1947         bo_add_8(p_bo, p_mem[i]);
1948 }
1949 
1950 static void bo_add_descr(bo_t *p_bo, uint8_t tag, uint32_t size)
1951 {
1952     bo_add_8(p_bo, tag);
1953     for (int i = 3; i>0; i--)
1954         bo_add_8(p_bo, (size>>(7*i)) | 0x80);
1955     bo_add_8(p_bo, size & 0x7F);
1956 }
1957 
1958 static bo_t *box_new(const char *fcc)
1959 {
1960     bo_t *box = malloc(sizeof(*box));
1961     if (!box)
1962         return NULL;
1963 
1964     bo_init(box);
1965 
1966     bo_add_32be  (box, 0);
1967     bo_add_fourcc(box, fcc);
1968 
1969     return box;
1970 }
1971 
1972 static bo_t *box_full_new(const char *fcc, uint8_t v, uint32_t f)
1973 {
1974     bo_t *box = box_new(fcc);
1975     if (!box)
1976         return NULL;
1977 
1978     bo_add_8     (box, v);
1979     bo_add_24be  (box, f);
1980 
1981     return box;
1982 }
1983 
1984 static void box_free(bo_t *box)
1985 {
1986     block_Release(box->b);
1987     free(box);
1988 }
1989 
1990 static void box_fix(bo_t *box)
1991 {
1992     box->b->p_buffer[0] = box->len >> 24;
1993     box->b->p_buffer[1] = box->len >> 16;
1994     box->b->p_buffer[2] = box->len >>  8;
1995     box->b->p_buffer[3] = box->len;
1996 }
1997 
1998 static void box_gather (bo_t *box, bo_t *box2)
1999 {
2000     box_fix(box2);
2001     box->b = block_Realloc(box->b, 0, box->len + box2->len);
2002     memcpy(&box->b->p_buffer[box->len], box2->b->p_buffer, box2->len);
2003     box->len += box2->len;
2004     box_free(box2);
2005 }
2006 
2007 static void box_send(sout_mux_t *p_mux,  bo_t *box)
2008 {
2009     box->b->i_buffer = box->len;
2010     sout_AccessOutWrite(p_mux->p_access, box->b);
2011     free(box);
2012 }
2013 
2014 static int64_t get_timestamp(void)
2015 {
2016     int64_t i_timestamp = time(NULL);
2017 
2018     i_timestamp += 2082844800; // MOV/MP4 start date is 1/1/1904
2019     // 208284480 is (((1970 - 1904) * 365) + 17) * 24 * 60 * 60
2020 
2021     return i_timestamp;
2022 }
VLC Main Development tree.RSSAtom
